package snsdbook.servlets;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import util.SQLUtil;

/**
 * Servlet implementation class RegisterServlet
 */
public class RegisterServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public RegisterServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	  request.setAttribute("register", "true");
	  
	  if (request.getSession().getAttribute("username") != null) {
      // Already logged in
      response.sendRedirect("Index");
    } else {
      // new guy
      RequestDispatcher view = request.getRequestDispatcher("/Register.jsp");
      view.forward(request, response);
    }
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	  String username = null;
    String password = null;
    String password_again = null;
    String full_name = null;
    String birthday = null;
    String email = null;
    String gender = null;
    String about = null;
    String type = null;
    String filename = null;
    InputStream image_content = null;
    String session_username = (String)request.getSession().getAttribute("username");
    try {
      @SuppressWarnings("unchecked")
      List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
      for (FileItem item : items) {
        if (item.isFormField()) {
          String fieldname = item.getFieldName();
          String fieldvalue = item.getString();
          if (fieldname.equals("type")) {
            type = fieldvalue;
          } else if (fieldname.equals("username")) {
            username = fieldvalue;
          } else if (fieldname.equals("password")) {
            password = fieldvalue;
          } else if (fieldname.equals("password_again")) {
            password_again = fieldvalue;
          } else if (fieldname.equals("full_name")) {
            full_name = fieldvalue;
          } else if (fieldname.equals("birthday")) {
            birthday = fieldvalue;
          } else if (fieldname.equals("email")) {
            email = fieldvalue;
          } else if (fieldname.equals("gender")) {
            gender = fieldvalue;
          } else if (fieldname.equals("about")) {
            about = fieldvalue;
          }
        } else {
          filename = FilenameUtils.getName(item.getName());
          InputStream filecontent = item.getInputStream();
          image_content = filecontent;
        }
      }
    } catch (Exception e) {
      throw new ServletException("Cannot parse multipart request.", e);
    }
    String errors = "";
    
    if (type.equals("change")) {
      request.setAttribute("profil", "true");

      username = session_username;
      password = password_again = SQLUtil.Query(
          "SELECT password FROM users WHERE username='" + username + "'")[0];
    }
    if (type.equals("register")) {
      request.setAttribute("register", "true");
      // Check that username is unique
      String[] res = SQLUtil.Query("SELECT username FROM users WHERE username='" + username + "'");
      if (res.length != 0) {
        errors += "Username already exists<br/>";
      }
      
      // ... and valid
      if (!username.matches("^[a-zA-Z0-9_-]{5,40}$")) {
        errors += "Username must be between 5 and 40 characters<br/>";
      }
    }
    // Check the password
    if (!password.matches("^[a-z0-9_-]{8,100}$")) {
      errors += "Password must be between 8 and 100 characters<br/>";
    }
    if (password.equals(username)) {
      errors += "Username and password must not be the same<br/>";
    }
    if (!password.equals(password_again)) {
      errors += "Password and Password(Again) must match<br/>";
    }
    // Check Full Name
    if (!full_name.matches("^.*\\w*\\s\\w*.*$")) {
      errors += "Full name must consists of at least 2 words<br/>";
    }
    // Check birthday
    if (!birthday.matches("^\\d\\d\\d\\d-\\d\\d-\\d\\d$")) {
      errors += "Birthday must be in form: YYYY-MM-DD<br/>";
    } else {
      // int y = Integer.valueOf(birthday.substring(0, 4));
      int m = Integer.valueOf(birthday.substring(5, 7));
      int d = Integer.valueOf(birthday.substring(8, 10));
      
      if (m <= 0 || m > 12) {
        errors += "Month must be between 1 and 12, inclusive.<br/>";
      } else {
        int[] days = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (d <= 0 || d > days[m-1]) {
          errors += "Day must be between 1 and " + days[m-1] + ", inclusive.<br/>";
        }
      }
    }
    // Check email
    if (!email.matches("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+" +
                       "(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$")) {
      errors += "Email format invalid<br/>";
    }
    
    // Check that email is unique
    String[] res = SQLUtil.Query("SELECT email FROM users WHERE email='" + email + "'");
    if (res.length != 0) {
      if (type.equals("register")) {
        errors += "Email already exists<br/>";
      } else if (type.equals("change") &&
                 !SQLUtil.Query("SELECT email FROM users WHERE username='" + username + "'")[0].equals(email)) {
        errors += "Email already exists<br/>";
      }
    }
    
    // Gender
    if (gender == null) {
      errors += "Please select a Gender<br/>";
    }
    
    // About not checked

    // Check filename
    if (image_content != null && filename != null && !filename.equals("")) {
      if (!filename.endsWith(".jpg") && !filename.endsWith(".jpeg") &&
          !filename.endsWith(".JPG") && !filename.endsWith(".JPEG")) {
        errors += "Image must be either jpg or jpeg<br/>";
      }
    } else {
      if (!type.equals("change")) {
        errors += "Please upload a (cute) avatar<br/>";
      }
    }
    if (errors.equals("")) {
      // OK
      // Writing to disk
      String putname = "";
      if (image_content != null && filename != null && !filename.equals("")) {
        putname = String.valueOf(System.currentTimeMillis()) + filename;
        System.out.println("Writing " + putname + " to disk...");
        String path = getServletContext().getRealPath("/avatar");
        IOUtils.copy(image_content, new FileOutputStream(new File(path + "/" + putname)));
      } else {
        putname = SQLUtil.Query("SELECT avatar FROM users where username='" + username + "'")[0];
      }
      
      // Delete previous entry
      if (type.equals("change")) {
        SQLUtil.Modify("DELETE FROM users WHERE username='" + username + "'");
      }
      
      // Write to SQL
      
      SQLUtil.Modify("INSERT INTO users(username, password, nama_lengkap, avatar, " +
                     "kelamin, email, about, birthday) " +
                     "VALUES('" + username + "', '" +
                                  password + "', '" +
                                  full_name + "', \"" +
                                  putname + "\", '" +
                                  gender +
                                  "', '" + email +
                                  "', '" + about + 
                                  "', '" + birthday + "')");
      
      // Write a Post about User (for search)
      
      // Processing Tag
      String tag = "user";
      String[] ret = SQLUtil.Query(
          "SELECT * FROM tag WHERE nama_tag = '" + tag + "'");
      if (ret.length == 0) {
        // No such tag, so insert a new one.
        SQLUtil.Modify("INSERT INTO tag(nama_tag, tag_seo, count) " +
                       "VALUES('" + tag + "', '" + tag.toLowerCase() +
                       "', '" + String.valueOf(0) + "')");
      }
      
      String id_tag = SQLUtil.Query(
          "SELECT id_tag FROM tag WHERE nama_tag = '" + tag + "'")[0];
      
      String text = "<a href='Profile?username=" + username + "'>" + username +
                    "'s Profile</a>";
      
      if (type.equals("register")) {
        SQLUtil.Modify("INSERT INTO berita(username, judul, judul_seo, isi_berita, " +
            " waktu, id_tag, gambar, video, dibaca, headline) " +
            "VALUES('" + username + "', '" +
                         username + "', '" +
                         username + "', \"" +
                         text + "\", '" +
                         String.valueOf(System.currentTimeMillis()) +
                         "', '" + id_tag +
                         "', '" + "" + 
                         "', '" + "" + 
                         "', '" + "0" + 
                         "', '" + "Y" + "')");
      }
      
      response.sendRedirect("ContentList");
    } else {
      // Retry
      request.setAttribute("errors", errors);
      request.setAttribute("username", username);
      request.setAttribute("full_name", full_name);
      request.setAttribute("birthday", birthday);
      request.setAttribute("email", email);
      request.setAttribute("gender", gender);
      request.setAttribute("about", about);
      RequestDispatcher view = request.getRequestDispatcher("/Register.jsp");
      view.forward(request, response);
    }
	}

}
